/*        
	Copyright (C) 2010- Peer internet solutions

	Copyright (C) 2013 Pontificia Universidad Catolica del Peru
	contact: http://avatar.inf.pucp.edu.pe/realidad-aumentada/
	address contact: Av. Universitaria 1801, San Miguel, Lima-Peru.

	This file is part of UbicAR PUCP.
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with This program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*
	Modified by: Pedro Carrión Castagnola
	Pontificia Universidad Catolica del Peru
	Direccion de Informatica Academica
	
	Modified by: Alvaro Roger Agüero Sánchez, Rodolfo Javier Galvez Meza
	Pontificia Universidad Catolica del Peru
	Departamento de Ingeniería
*/
package org.grupoavatar.guiaubicua;

import java.util.ArrayList;
import java.util.List;

import org.grupoavatar.guiaubicua.dialogos.POI_Locked_Dialog;
import org.grupoavatar.guiaubicua.gestores.GestorConfiguracion;
import org.grupoavatar.guiaubicua.mix.DataView;
import org.grupoavatar.guiaubicua.mix.Marker;
import org.grupoavatar.guiaubicua.mix.MixContext;
import org.grupoavatar.guiaubicua.mix.MixState;
import org.grupoavatar.guiaubicua.mix.gui.PaintScreen;
import org.grupoavatar.guiaubicua.punto.MasterActivity;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockMapActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class VMapa extends SherlockMapActivity implements LocationListener {

	private static List<Overlay> mapOverlays;
	private List<Marker> markerList;
	private static DataView dataView;
	private static GeoPoint startPoint;
	private MixContext mixContext;
	private MapView mapView;
	static VMapa map;
	private static Context thisContext;
	private LocationManager locationMgr;
	int focusMylocation;
	private ProgressDialog pd;
	private boolean first;

	public Dialog d;
	
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
//		requestWindowFeature(Window.FEATURE_NO_TITLE);
		dataView = VInicial.dataView;
		if (dataView != null) {
			mixContext = dataView.getContext();
			if (VBusqueda.primeraConsulta) {
				VInicial.dataView.setDefaultMarkerList();
				if (VInicial.dataView.getDataHandler().getMarkerListTotal().size() > 0)
					VBusqueda.primeraConsulta = false;
			}
			markerList = dataView.getDataHandler().getMarkerList();

		}
		//ESTO ES NUEVO
		GestorConfiguracion.dWindow = new PaintScreen();
		GestorConfiguracion.activity = (Activity) this;
		//FIN NUEVO
		map = this;
		setMapContext(this);
//		mapView = new MapView(this, "0WsvT9zzKMfH5JDZMDlkWVFsKciLKe-1BncQ9eA");
//		mapView = new MapView(this, "AIzaSyBmrMaTiuKAZNXUXezVfGsNwzymj_lKkjM");
		mapView = new MapView(this, "0rYQU1d4CmEVINKGKWOLIBMIVXDxwaneJQPrZdA");
		mapView.displayZoomControls(true);
		mapView.setBuiltInZoomControls(true);
		mapView.setClickable(true);
		mapView.setSatellite(false);
		mapView.setEnabled(true);

		this.setContentView(mapView);
		createOverlay();
		
		focusMylocation = 2;
		first = true;
		setStartPoint(false);
		
		if (!DataView.viendoUnicoMarker)	{
			setProgressDialog();
		}
		
		getSherlock().getActionBar().setTitle("Mapa");
	}

	public void setStartPoint(boolean forzarVerMiUbicacion) {
		Location location = null;
		if (mixContext != null) {
			location = mixContext.getCurrentLocation();
		}
		
		double latitude;
		double longitude;
		if (location != null) {
			latitude = location.getLatitude() * 1E6;
			longitude = location.getLongitude() * 1E6;
		} else { // si no logro encontrar ninguna ubicación se ubicará en el  jardin central
			latitude = (-12.069071) * 1E6;
			longitude = (-77.079212) * 1E6;
		}

		MapController controller = mapView.getController();
		startPoint = new GeoPoint((int) latitude, (int) longitude);
		
		CustomItem item = new CustomItem(startPoint, "", "", this.getResources().getDrawable(R.drawable.loc_icon));
		SitesOverlay myLocation = new SitesOverlay(this, item);
		if (first)	{
			first = false;		
		}
		else	{
			mapView.getOverlays().remove(mapView.getOverlays().size()-1);
		}
			
		mapView.getOverlays().add(myLocation);
		

		
		if (focusMylocation != 0) {
			// centro el mapa en mi ubicación actual si no estoy viendunicomarker
			if ( (!DataView.viendoUnicoMarker) || (forzarVerMiUbicacion) )	{
				controller.setCenter(startPoint);
			}
			else	{
				GeoPoint markerpoint = MasterActivity.getPoiCoordinates();
				if (markerpoint!=null)	{
					controller.setCenter(markerpoint);
				}
				else	{
					controller.setCenter(startPoint);
				}
			}
			// hago zoom sólo en el primer focus
			if (focusMylocation == 2)	{
				boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
				if (tabletSize) {
					controller.setZoom(19);
				} else {
					controller.setZoom(18);
				}
			}
				
			--focusMylocation;
		}
		mapView.invalidate();
	}

	public void createOverlay() {
		SitesOverlay sites = new SitesOverlay(this, markerList);
		mapView.getOverlays().add(sites);
	}

	@Override
	protected void onPause() {
		super.onPause();
		try {
			locationMgr.removeUpdates(this);
		} catch (Exception ignore) {
		}
		locationMgr = null;
//		me.disableCompass();
//		me.disableMyLocation();
	}

	public void setErrorDialog(){
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(getString(R.string.connection_error_dialog));
		builder.setCancelable(false);
		
		/*Retry*/
		builder.setPositiveButton(R.string.connection_error_dialog_button1, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
	        	finish();
				Intent i = new Intent(VInicial.getContext(), VDownloading.class);
				i.putExtra("sigV", "mapa");
				startActivity(i);
			}
		});
		/*Open settings*/
		builder.setNeutralButton(R.string.connection_error_dialog_button2, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				Intent intent1 = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 
				startActivityForResult(intent1, 42);
			}
		});
		/*Close application*/
		builder.setNegativeButton(R.string.connection_error_dialog_button3, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				finish();
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	public void setProgressDialog(){
		pd = new ProgressDialog(this);
		pd.setMessage("Obteniendo ubicación");
		
		pd.setButton("Cancelar", new DialogInterface.OnClickListener() 
	    {
	        public void onClick(DialogInterface dialog, int which) 
	        {
	        	String nmc = mixContext.noMarkersCheck();
	        	if (nmc != null)
	        		Toast.makeText(mixContext, nmc, Toast.LENGTH_LONG).show();
	        	return;
	        }
	    });
		pd.show();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		thisContext = this;
		if (DataView.volverInicio)	{
			finish();
			return;
		}
		
		int estadoDescarga = VInicial.dataView.getEstado();
        if ((estadoDescarga != MixState.DONE) || (DataView.actualizarMarkers)) {
        	DataView.actualizarMarkers = false;
        	//VInicial.dataView.applyCatFilter(VInicial.dataView.getDataHandler().getMarkerListTotal());
			Intent i = new Intent(VInicial.getContext(), VDownloading.class);
			i.putExtra("sigV", "mapa");
			startActivity(i);
        	this.finish();
			return;
        }
		
		//cuando busco un lugar viendounicomarker en mapa y vuelvo al mapa, markerlist debe actualizarce
		markerList = dataView.getDataHandler().getMarkerList();
		try {
			Criteria c = new Criteria();

			c.setAccuracy(Criteria.ACCURACY_FINE);
			// c.setBearingRequired(true);

			locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			locationMgr.requestLocationUpdates(
					LocationManager.NETWORK_PROVIDER, 10000, 10, this);
			locationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
					10000, 10, this);

			if ( (!locationMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) && 
					 (!locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) )	{
				if (!DataView.viendoUnicoMarker)	{
					pd.dismiss();
				}
				setErrorDialog();
			}

			try {
				Location gps = locationMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
				Location network = locationMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
				
				 //if there are both values use the latest one
	             if(gps!=null && network!=null){
	                 if(gps.getTime()>network.getTime())
	                	 mixContext.curLoc = gps;
	                 else
	                	 mixContext.curLoc = network;
	             }
				 else if (gps != null)
					 mixContext.curLoc = gps;
				 else if (network != null)
					 mixContext.curLoc = network;
			} catch (Exception ex2) {
				ex2.printStackTrace();
			}
			mixContext.setLocationAtLastDownload(mixContext.curLoc);

		} catch (Exception ex) {
			Log.d("mixare", "GPS Initialize Error", ex);
		}
//		me.enableCompass();
//		me.enableMyLocation();		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
//		int base = Menu.FIRST;
		/* define the first */
//		MenuItem item1 = menu.add(base, base, base, getString(R.string.menu_item_1)); //buscar por categoria
//		MenuItem item2 =menu.add(base, base+1, base+1,  getString(R.string.menu_item_2)); //buscar por servicios
//		MenuItem item3 =menu.add(base, base+2, base+2,  getString(R.string.menu_item_3)); //buscar (texto)
//		MenuItem item4 = menu.add(base, base + 3, base + 3, getString(R.string.menu_item_4)); //ver en lista
//		MenuItem item5 = menu.add(base, base + 4, base + 4, getString(R.string.map_menu_cam_mode)); //ver en RA
//		MenuItem item6 = menu.add(base, base + 5, base + 5, getString(R.string.map_my_location)); //mi ubicacion
//		
//		item1.setIcon(R.drawable.ic_menu_filtrar);
//		item2.setIcon(android.R.drawable.ic_menu_share);
//		item3.setIcon(android.R.drawable.ic_menu_search);
//		item4.setIcon(android.R.drawable.ic_menu_sort_by_size);
//		item5.setIcon(R.drawable.ic_menu_ar);
//		item6.setIcon(android.R.drawable.ic_menu_mylocation);

		MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.menu_mapa, menu);
		
		if (DataView.viendoUnicoMarker)	{
			menu.findItem(R.id.mapaMenuCategoria).setVisible(false);
			menu.findItem(R.id.mapaMenuServicio).setVisible(false);
			menu.findItem(R.id.mapaMenuBuscar).setVisible(false);
			menu.findItem(R.id.mapaMenuVerEnLista).setVisible(false);
		}
		
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent i;
		switch (item.getItemId()) {
			case R.id.mapaMenuCambiarVista:
				if (mapView.isSatellite())
					mapView.setSatellite(false);
				else
					mapView.setSatellite(true);
				break;
			case R.id.mapaMenuCategoria: //Filtro
				i = new Intent(VInicial.getContext(), VFiltro.class);
				startActivity(i);
				break;
			case R.id.mapaMenuServicio: //Buscar por servicio
				i = new Intent(VInicial.getContext(), VServicios.class);
				startActivity(i);
				break;
			case R.id.mapaMenuBuscar: //buscar (texto)
				if (DataView.enBusqueda == false)	{
					i = new Intent(VInicial.getContext(), VBusqueda.class);
					startActivity(i);
				}
				finish();
				break;
			case R.id.mapaMenuVerEnLista: //Ver en lista
				i = new Intent(VInicial.getContext(), VDownloading.class);
				i.putExtra("sigV", "lista");
				startActivity(i);
				break;
			case R.id.mapaMenuVerEnRA: //ver en RA
				i = new Intent(VInicial.getContext(), VDownloading.class);
				i.putExtra("sigV", "ar");
				startActivity(i);
				finish();
				break;
			case R.id.mapaMenuMiUbicacion:	//mi ubicación
				focusMylocation = 1;
				setStartPoint(true);
				break;
		}

		return true;
	}
	
	public List<Marker> getMarkerList() {
		return markerList;
	}

	public DataView getDataView() {
		return dataView;
	}

	public List<Overlay> getMapOverlayList() {
		return mapOverlays;
	}

	public void setMapContext(Context context) {
		thisContext = context;
	}

	public static Context getMapContext() {
		return thisContext;
	}

	public void startPointMsg() {
		Toast.makeText(getMapContext(), R.string.map_current_location_click,
				Toast.LENGTH_LONG).show();
	}

	// Métodos implementados por LocationListener, es muy similar a VAR
	@Override
	public void onLocationChanged(Location location) {
		try {
			Log.v(VInicial.TAG,
					"Location Changed: " + location.getProvider() + " lat: "
							+ location.getLatitude() + " lon: "
							+ location.getLongitude() + " alt: "
							+ location.getAltitude() + " acc: "
							+ location.getAccuracy());

			mixContext.setLocationAtLastDownload(location);
			
			if (mixContext.isBetterLocation(location, mixContext.curLoc))	{
				synchronized (mixContext.curLoc) {
					mixContext.curLoc = location;
				}
				
				if (!VInicial.dataView.isFrozen())
					VInicial.dataView.getDataHandler().onLocationChanged(location);

				Log.d(VInicial.TAG, "Cambiando ubicacion actual en el mapa");
				setStartPoint(false);
			}
			// setGpsEnabled(true);
			if ((!DataView.viendoUnicoMarker) && (pd.isShowing()))	{
				pd.dismiss();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {

	}

}

class SitesOverlay extends ItemizedOverlay<CustomItem> {

	private List<CustomItem> items = new ArrayList<CustomItem>();
	private VMapa vmapa;
	
	public SitesOverlay(VMapa VMapa, CustomItem mylocation) {
	    super (boundCenterBottom(mylocation.getMarker()));
	    this.vmapa = VMapa;
	    items.add(mylocation);
	    populate();
	}
	
	public SitesOverlay(VMapa VMapa, List<Marker> markerList) {
	    super(null);
	    
	    this.vmapa = VMapa;
	    Resources resources = VMapa.getResources();
	    
		for (Marker marker : markerList) {
			if (marker.isActive()) {
				GeoPoint point = new GeoPoint((int) (marker.getLatitude() * 1E6), (int) (marker.getLongitude() * 1E6));
				try {
					Drawable icon = resources.getDrawable(marker.getCircleIcon());
					icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
					boundCenter(icon);				
					CustomItem item = new CustomItem(point,marker.getID(), "", icon);
				    items.add(item);
				} catch (NotFoundException e) {
					
				} catch (Exception e) {
					
				}
			}
		}
	    populate();
	}

	@Override
	protected CustomItem createItem(int i) {
		return items.get(i);
	}

	@Override
	public int size() {
		return items.size();
	}

	 @Override
	 protected boolean onTap(int index){
		String itemId = getItem(index).getTitle();
		List<Marker> markerList = vmapa.getMarkerList();
		
		for (Marker marker : markerList) {
			if (marker.getID().equals(itemId)) {
				if (vmapa.d != null) {
					try {
						vmapa.d.dismiss();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				if (DataView.viendoUnicoMarker)	{					
					vmapa.d = new POI_Locked_Dialog(marker,VMapa.getMapContext());
					//ACA se debe cambiar en caso se quiera que NO aparezca el locked dialog en vista de un solo elemento
					/*
					vmapa.finish();
					*/
				}
				else	{					
					vmapa.d = new POI_Locked_Dialog(marker,VMapa.getMapContext());
				}
				return true;
			}
		}
		return false;
	 }
	 
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow)	{
	    if(!shadow)	{
	        super.draw(canvas, mapView, false);
	    }
	    GestorConfiguracion.dWindow.setWidth(canvas.getWidth());
		GestorConfiguracion.dWindow.setHeight(canvas.getHeight());
		GestorConfiguracion.dWindow.setCanvas(canvas);
	}
}

class CustomItem extends OverlayItem {

	Drawable marker=null;
    
    CustomItem(GeoPoint pt, String name, String snippet,
               Drawable marker) {
      super(pt, name, snippet);
      this.marker=marker;
    }
    
    @Override
    public Drawable getMarker(int stateBitset) {
      Drawable result = marker;
      setState(result, stateBitset);
      return(result);
    }
    
    public Drawable getMarker() {
		return marker;
	}
  }